/*===========================================================
 
 .---=||||[ B L O O D Y ]|||||=====================----------....
 |                                                              |
 |    THE  M O S T   B L O O D Y  GAME EVER!                    |
 |                                                              |
 |    bloody harvest is coming... soon,                         |
 |                                              heil Satan!     |
 !                                                              !
 .                                                              ,
  ~~~~-------------================================|||||||||==-~




 Name-Space: {core, logic, editor}
 Module: {draw, coll, scgr, ...}
 Class: <name of class>
 Last modification:  <author>, <time>

 TODO:
 <-------- todo #1 ---------->
 <-------- todo #2 ---------->
 <-------- todo #3 ---------->
        ............
 <-------- todo #n ---------->

 FIX:
 <-------- fix #1 ----------->
 <-------- fix #1 ----------->
         ..........
 <-------- fix #n ----------->




 
 
 ============================================================*/
#include "core/draw/Image.h"
#include "core/exceptions.h"

namespace core
{
    namespace draw 
    {

static bool initialised = false;

#ifdef USE_FREEIMAGE

#include <FreeImage.h>


void Image::load(const char *filename){
	if (!initialised){
		FreeImage_Initialise();
		initialised = true;
	}

	FIBITMAP* bmp = 0;
	FREE_IMAGE_FORMAT format = FIF_UNKNOWN;

	format = FreeImage_GetFileType(filename, 0);
	if (FIF_UNKNOWN == format){
		format = FreeImage_GetFIFFromFilename(filename);
	}
	if ((FIF_UNKNOWN != format) && FreeImage_FIFSupportsReading(format)){
		bmp = FreeImage_Load(format, filename, 0);
		if (0 == bmp) throw EFileNotFound(filename);

		width = FreeImage_GetWidth(bmp);
		height = FreeImage_GetHeight(bmp);
		unsigned short bpp = FreeImage_GetBPP(bmp);
		unsigned char* ptr = 0;
		FIBITMAP* swap;
		switch (bpp){
		case 8:
		case 16:
			swap = FreeImage_ConvertTo24Bits(bmp);
			FreeImage_Unload(bmp);
			bmp = swap;
		case 24:
			type = RGB8;
			bitmap = new unsigned char[width * height * 3];
			ptr = (unsigned char *)FreeImage_GetBits(bmp);
			for (unsigned long i = 0; i < width * height * 3; i++) bitmap[i] = ptr[i];
			break;


		case 32:
			type = RGBA8;
			bitmap = new unsigned char[width * height * 4];
			ptr = (unsigned char *)FreeImage_GetBits(bmp);
			for (unsigned long i = 0; i < width * height * 4; i++) bitmap[i] = ptr[i];
			break;

		default:
			throw InvalidOperationException("Wrong image BPP");
		}

	}
	else throw FileNotFoundException(filename);

};


#else // defined USE_FREEIMAGE


#include <IL/il.h>

void Image::load(const char *filename){
	if (!initialised){
            ilInit();
            initialised = true;

	}

        ILuint bmp = 0;
        ilGenImages(1, &bmp);
        ilBindImage(bmp);
	ilLoadImage((char*)filename);
	ILenum err = ilGetError();
        if (err != IL_NO_ERROR) 
        	throw ILException(err,filename);
        width = ilGetInteger(IL_IMAGE_WIDTH);
        height = ilGetInteger(IL_IMAGE_HEIGHT);
        unsigned short bpp = ilGetInteger(IL_IMAGE_BITS_PER_PIXEL);
	unsigned char* ptr = 0;
	switch (bpp){
		case 8:
		case 16:
                    ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE);
		case 24:
					ilConvertImage(IL_BGR, IL_UNSIGNED_BYTE);
                    type = RGB8;
                    bitmap = new unsigned char[width * height * 3];
                    ptr = (unsigned char *)ilGetData();
                    for (unsigned long i = 0; i < width * height * 3; i++) bitmap[i] = ptr[i];
                    break;

		case 32:
                    type = RGBA8;
					ilConvertImage(IL_BGRA, IL_UNSIGNED_BYTE);
                    bitmap = new unsigned char[width * height * 4];
                    ptr = (unsigned char *)ilGetData();
                    for (unsigned long i = 0; i < width * height * 4; i++) bitmap[i] = ptr[i];
                    break;

		default:
                    throw InvalidOperationException("Wrong image BPP");
        }


};


#endif

GLenum Image::getGLType(){
	switch( type ){
		case RGB8:
			return GL_BGR;//GL_RGB;


		case RGBA8:
			return GL_BGRA;//GL_RGBA;

		default:
			return GL_RGB;
	}
}

    }
}
